package com.joe.oxm;

import org.dom4j.Attribute;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.xml.sax.XMLReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;


@SpringBootApplication
public class OxmApplication implements ApplicationRunner {

    Logger logger = LoggerFactory.getLogger(OxmApplication.class);
    public static void main(String[] args) {
        SpringApplication.run(OxmApplication.class, args);
    }

    @Autowired
    Customer customer;
//JAXB 本例参考 https://www.cnblogs.com/moonlightpoet/p/5533313.html
//还有一个小插件使用对敌 非常好用的一个maven小插件"maven-jaxb2-plugin" https://www.jianshu.com/p/f2803b407ed4

    @Override
    public void run(ApplicationArguments args) throws Exception {
        //将xml转换成java bean，但首先需要将xml按xsd进行验证，再进行转换 需要用到dom4j
        //获取sax解析工厂实例并设置是否验证及是否需要命名空间启用
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        saxParserFactory.setValidating(true);
        saxParserFactory.setNamespaceAware(true);

        //获取sax解析实例，并将这个sax实例与相应的xsd文件相关联
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //设置解析实例是xml实例
        saxParser.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        //设置与这个saxParser实例相关的用于验证xml的xsd文件
        saxParser.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaSource","file:" + "file.xsd");
        //通过saxParser实例获取xmlReader对象
        XMLReader xmlReader = saxParser.getXMLReader();
        //设置xmlReader需要验证这个动作
        xmlReader.setFeature("http://xml.org/sax/features/validation",true);
        //设置要验证时的handler
        org.dom4j.util.XMLErrorHandler xmlErrorHandler = new org.dom4j.util.XMLErrorHandler();
        xmlReader.setErrorHandler(xmlErrorHandler);

        //将需要验证的xml文件通过xmlReader读进来，就会开始进行验证
        String dir=System.getProperty("user.dir");
        xmlReader.parse(dir+File.separator+"file.xml");

        //查看验证结果
        if(xmlErrorHandler.getErrors().hasContent())
        {
            System.out.println("xml verivation has errors:");
            OutputFormat outputFormat = OutputFormat.createPrettyPrint();
            outputFormat.setEncoding("utf-8");
            XMLWriter xmlWriter = new XMLWriter(outputFormat);
            xmlWriter.write(xmlErrorHandler.getErrors());

            Attribute attribute = xmlErrorHandler.getErrors().element("error").attribute("line");
            String value = attribute.getValue();
            int line = Integer.parseInt(value);
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(dir+File.separator+"file.xml"),"utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            System.out.println(line);
            String s = null;
            int i=0;
            while((s = bufferedReader.readLine())!=null)
            {
                if(i==line+1)
                    logger.info("错误之后的地方*****>" + s);
//                    System.out.println("错误之后的地方*****>" + s); //将xml文件中错误的地方的前一句和后一句也打印出来
                if(i==line)
                    logger.error("错误之处--->第"+line+"行: " + s);
//                    System.out.println("----->" + s); //将xml文件中错误的地方的前一句和后一句也打印出来
                if(i==line-1)
                    logger.info("错误之后的地方*****>" + s);
//                    System.out.println("错误之前的地方*****>" + s); //将xml文件中错误的地方的前一句和后一句也打印出来
                i++;
            }
        }
        else {
            System.out.println("pass ok");
        }

    }

    //    @Override
    public void run2(ApplicationArguments args) throws Exception {
        //将xml转换成java bean对象
        try {
            String dir=System.getProperty("user.dir");
            File file = new File(dir+File.separator+"file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Customer customer = (Customer) jaxbUnmarshaller.unmarshal(file);
            System.out.println(customer);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

//    @Override
    public void run1(ApplicationArguments args) throws Exception {
        //JAXBMarshallExample
        //将java bean对象转换成XML
        //JAXB编组（marshall）对象成XML。
//        Customer customer = new Customer();
        customer.setId(1000);
        customer.setName("moon");
//        customer.setSex("fame");//如果没有这一句则xml中没有这个元素 ,将来由xml生成java bean会不会出错呢？不会出错，使用数据类型的默认值


        try {
            String dir=System.getProperty("user.dir");
            File file = new File(dir+File.separator+"file.xml");
//            File file = new File("C:\\file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            jaxbMarshaller.marshal(customer, file);
            jaxbMarshaller.marshal(customer, System.out);
            System.out.println("对象转xml OK");

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}
